package com.bjc.principle.singleton.type06;


import java.io.*;
import java.lang.reflect.Constructor;

/**
 * @program: DesignPattern
 * @description:
 * @author: bjc
 * @create: 2020-12-13 20:48
 */
public class SingletonTest06 {
    public static void main(String[] args) throws Exception {
//        Singleton instance1 = Singleton.getInstance();
//        Singleton instance2 = Singleton.getInstance();
//        System.out.println(instance1==instance2);
//        System.out.println(instance1.hashCode());
//        System.out.println(instance2.hashCode());


        //序列化反序列化破坏单例模式
//        SingletonTest06.writeObject2File();
//        SingletonTest06.readObjectFromFile();
//        SingletonTest06.readObjectFromFile();


        //反射破坏单例模式
        Class clazz = Singleton.class;
        Constructor constructor = clazz.getDeclaredConstructor();
        constructor.setAccessible(true);
        Singleton s1 = (Singleton) constructor.newInstance();
        Singleton s2 = (Singleton) constructor.newInstance();
        System.out.println(s1==s2);
    }

    //从文件读取数
    public static void readObjectFromFile() throws Exception{
        //创建对象输入流
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("C:\\Users\\bjc10\\Desktop\\a.txt"));
        //读取对象
        Singleton instance = (Singleton)ois.readObject();
        System.out.println(instance.hashCode());
        //释放资源
        ois.close();
    }

    //向文件中写数据（对象）
    public static void writeObject2File() throws Exception{
        //1.获取Singleton对象
        Singleton instance = Singleton.getInstance();
        //2.创建对象输出流对象
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("C:\\Users\\bjc10\\Desktop\\a.txt"));
        //3.写对象
        oos.writeObject(instance);
        //4.释放资源
        oos.close();
    }
}

//静态内部类  推荐使用
class Singleton implements Serializable {
    private static volatile Singleton instance;


    private static boolean flag = false;

    //私有化构造器
    private Singleton(){
        synchronized (Singleton.class){
            //判断flag的值是否是true,如果是true,说明非第一次访问，如果是false的话，说明是第一次
            if (flag){
                throw new RuntimeException("不能创建多个对象");
            }
            flag = true;
        }
    }

    //写一个静态内部类，该类中有一个静态属性Singleton
    private static class SingletonInstance{
        private static final Singleton INSTANCE = new Singleton();
    }

    //提供一个静态的共有方法，直接返回SingletonInstance.INSTANCE
    public static synchronized Singleton getInstance(){
        return SingletonInstance.INSTANCE;
    }

    //当进行反序列化时，会自动调用该方法，将该方法的返回值直接返回
    //https://www.bilibili.com/video/BV1Np4y1z7BU?p=31&spm_id_from=pageDriver
    public Object readResolve(){
        return SingletonInstance.INSTANCE;
    }
}
